package com.quinn.myDemo.lever;

import java.math.BigDecimal;
import java.math.RoundingMode;

import org.apache.commons.math3.analysis.UnivariateFunction;
import org.apache.commons.math3.analysis.solvers.BisectionSolver;
import org.apache.commons.math3.analysis.solvers.UnivariateSolver;

/**
 * Demo20251011
 *
 * @author HanQuinn
 * Date: 2025/10/11
 * Time: 13:41
 */
public class Demo20251011 {

    public static void main(String[] args) {
        double preRate = 1.02;
        double sourcePrice = 2.2;
        double targetPrice = 8.2;
        // 本金capitalBalance, 负债debtBalance, 持股手数holdHands, 股价price
        BigDecimal oCapitalBalance = new BigDecimal("1000000");
        BigDecimal oDebtBalance = new BigDecimal("0");
        BigDecimal oHoldHands = new BigDecimal("4500");
        BigDecimal oPrice = new BigDecimal("2.2");
        BigDecimal leverRate = new BigDecimal("1.7");
        BigDecimal DECIMAL_100 = new BigDecimal("100");

        Balance balance = new Balance(oCapitalBalance, oDebtBalance, oHoldHands, oPrice);
        int circleCount = getCircleCount(sourcePrice, targetPrice, preRate);
        for (int i = 0; i < circleCount; i++) {
            BigDecimal oldPrice = balance.getPrice();
            // 本金
            BigDecimal oldDebtBalance = balance.getDebtBalance();
            BigDecimal oldHoldHands = balance.getHoldHands();
            BigDecimal newPrice = oldPrice.multiply(new BigDecimal(preRate));
            BigDecimal newTotalPrice = oldHoldHands.multiply(newPrice).multiply(DECIMAL_100);
            BigDecimal newNetBalance = newTotalPrice.subtract(oldDebtBalance);
            //可用新融资额度
            BigDecimal nearPromoteDebt = newNetBalance.multiply(leverRate).subtract(balance.getTotalPrice());
            //新增持股手数

            BigDecimal promoteHoldHands = (nearPromoteDebt.divide(newPrice.multiply(DECIMAL_100), 0, RoundingMode.FLOOR));
            BigDecimal newDebtBalance = promoteHoldHands.multiply(newPrice).multiply(DECIMAL_100).add(oldDebtBalance);
            BigDecimal newHoldHands = promoteHoldHands.add(oldHoldHands);

            balance.setPrice(newPrice.setScale(4, RoundingMode.HALF_UP));
            balance.setDebtBalance(newDebtBalance.setScale(4, RoundingMode.HALF_UP));
            balance.setHoldHands(newHoldHands.setScale(4, RoundingMode.HALF_UP));
        }
        BigDecimal netBalance = balance.getNetBalance();
        System.out.println("netBalance = " + netBalance);
        BigDecimal totalPrice = balance.getTotalPrice();
        System.out.println("totalPrice = " + totalPrice);
        BigDecimal debtBalance = balance.getDebtBalance();
        System.out.println("debtBalance = " + debtBalance);
        BigDecimal profitBalance = balance.getProfitBalance();
        System.out.println("profitBalance = " + profitBalance);
        System.out.println("balance.toString() = " + balance.toString());

    }

    private static int getCircleCount(double sourcePrice, double targetPrice, double perRate) {
        UnivariateFunction function = new UnivariateFunction() {
            @Override
            public double value(double x) {
                return sourcePrice * Math.pow(perRate, x) - targetPrice;
            }
        };
        UnivariateSolver solver = new BisectionSolver();
        double x = solver.solve(1000, function, 0, 100, 1e-6);
        return (int) Math.ceil(x);
    }
}
